const electron = require('electron')
const path = require('path')
const { spawn } = require('child_process')
const webpack = require('webpack')
const WebpackDevServer = require('webpack-dev-server')
const { getPort } = require('portfinder')

const main = require('./webpack.main')
const renderer = require('./webpack.renderer')

let electronProcess, manualRestart, hotMiddleware
/**
 * 运行主进程
 */
function prepareMain() {
    return new Promise((resolve, reject) => {
        const compiler = webpack(main)
        compiler.hooks.watchRun.tapAsync('watch-run', (compilation, done) => {
            hotMiddleware && hotMiddleware.publish({ action: 'compiling' })
            done()
        })
        compiler.watch({}, (error, stats) => {
            if (error) {
                console.log('[app] error:', error, stats)
                return
            }
            if (electronProcess && electronProcess.killed) {
                manualRestart = true
                process.kill(electronProcess.pid)
                electronProcess = null
                // restart
                run()
                setTimeout(() => (manualRestart = false), 5000)
            }
            console.log('[app] compiled');
            resolve()
        })
    })
}
/**
 * 准备 renderer 进程
 */
function prepareUI() {
    return new Promise((resolve, reject) => {
        const compiler = webpack(renderer)
        const serverOption = Object.assign(renderer.devServer, {
            stats: { colors: true },
            contentBase: path.resolve(__dirname, '../'),
            hot: true,
            host: 'localhost'
        })
        // 包含 HMR 入口起点
        WebpackDevServer.addDevServerEntrypoints(renderer, serverOption)
        const webpackDevServer = new WebpackDevServer(compiler, serverOption)
        getPort({ port: serverOption.port }, (error, port) => {
            if (error) {
                console.log('[Renderer]', error);
                reject()
            }
            webpackDevServer.listen(port, 'localhost', (error) => {
                if (error) {
                    console.log('[Renderer] listen:', error);
                    reject()
                }
                else resolve()
            })
        })
        
    })
}
/**
 * development 模式下启动 electron
 */
function run() {
    // for debug
    let args = ['--inspect=5858', path.join(__dirname, '../dist/main.js')]
    const execTool = process.env.npm_execpath
    const index = execTool.endsWith('yarn.js') ? 3 : execTool.endsWith('npm-cli.js') ? 2 : args.length
    args = args.concat(process.argv.slice(index))
    console.log('[app] args', args);
    // start electron process
    electronProcess = spawn(electron, args)
    electronProcess.stdout.on('data', (data) => {
        console.log('[app]', data.toString('utf8'));
    })
    electronProcess.stderr.on('data', (data) => {
        console.log('[app]', data.toString('utf8'));
    })
    electronProcess.on('close', () => {
        if (!manualRestart) process.exit()
    })
}
/**
 * 启动
 */
function init() {
    Promise.all([prepareUI(), prepareMain()])
        .then(() => {
            console.log('[all] done');
            run()
        })
        .catch((error) => {
            console.log('[prepare] error:', error)
        })
}

init()
// prepareUI()